﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Linq;

namespace Flare.Controls
{
    public partial class NetworkPoint : UserControl, IPointControl, INotifyPropertyChanged
    {
        DB.Entity.EndpointMap data = new DB.Entity.EndpointMap();
        public NetworkPointType PointType { get { return data.dev_type; } }
        public string PointName { get { return data.dev_name; } }
        public int ID
        {
            get
            {
                return data.id.Value;
            }
            set
            {
                data.id = value;
            }
        }
        public string IP
        {
            get
            {
                return data.dev_ip;
            }
        }
        public Point CenterPoint
        {
            get
            {
                return new Point(this.Margin.Left + this.ActualWidth / 2, this.Margin.Top + this.ActualHeight / 2);
            }
        }
        bool? _ping_ok = null;
        public bool? IsAvailable
        {
            get { return _ping_ok; }
            set
            {
                if (_ping_ok != value)
                {
                    _ping_ok = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("IsAvailable"));
                }
            }
        }

        public NetworkPoint(string name, double left_position, double top_position,
            NetworkPointType type = NetworkPointType.cloud, string checkip = null)
        {
            data.dev_name = name;
            data.dev_type = type;
            data.dev_ip = checkip;
            this.Margin = new Thickness(left_position, top_position, 0, 0);

            InitializeComponent();
            
            if (checkip != null)
            {
                if (glob.NetworkList.Values.Count(m => m.ip == checkip) != 0)
                {
                    NetworkEntityStatus c_ep = glob.NetworkList.Values.First<NetworkEntityStatus>(m => m.ip == checkip);
                    if (c_ep.delay.HasValue)
                    {
                        IsAvailable = true;
                    }
                    else
                    {
                        IsAvailable = false;
                    }

                    c_ep.PropertyChanged += (s, e) => {
                        if (c_ep.delay.HasValue)
                        {
                            IsAvailable = true;
                        }
                        else {
                            IsAvailable = false;
                        }
                    };
                }
                else
                {
                    System.Timers.Timer timer_ping_check = new System.Timers.Timer(5000);
                    timer_ping_check.Elapsed += (s, e) =>
                    {
                        CheckConnect(checkip);
                    };
                    timer_ping_check.Start();
                }
            }
            else {
                IsAvailable = null;
            }

            #region лаг с измерением размера при инициализации
            this.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            this.Arrange(new Rect(0, 0, 20, 20));
            #endregion
        }
        
        Point StartXY = new Point();
        private void UserControl_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.CaptureMouse();
            StartXY = e.GetPosition(this);
            e.Handled = true;
        }
        private void UserControl_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (this.IsMouseCaptured)
            {
                System.Windows.Point position = e.GetPosition(this.Parent as Grid);

                double dec_x = position.X - StartXY.X;
                double dec_y = position.Y - StartXY.Y;

                // привязка к сетке
                dec_x = (int)(dec_x / 5) * 5;
                dec_y = (int)(dec_y / 5) * 5;

                if (dec_x < 0) dec_x = 0;
                if (dec_y < 0) dec_y = 0;
                this.Margin = new Thickness(dec_x, dec_y, 0, 0);
                eMoveCenterPoint(dec_x + this.ActualWidth / 2, dec_y + this.ActualHeight / 2);
            }
            e.Handled = true;
        }
        private void UserControl_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.ReleaseMouseCapture();
            data.pointA_X = this.Margin.Left;
            data.pointB_Y = this.Margin.Top;
            new DB.endpoints_map().Edit(data);
        }
        
        private void CheckConnect(string checkip)
        {
            var result = new System.Net.NetworkInformation.Ping().Send(checkip, 4000);
            if (result.Status == System.Net.NetworkInformation.IPStatus.Success)
            {
                IsAvailable = true;
            }
            else {
                IsAvailable = false;
            }
        }

        public event dPointMove eMoveCenterPoint = delegate { };
        public event HandledEventHandler eRemove = delegate { };
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        private void LedConnect_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (string.IsNullOrEmpty(IP) == false)
            {
                glob.kernel.ShowPage(typeof(Pages.Reports.NetworkStatisticHistory), IP);
                Debug.WriteLine(IP);
            }
            e.Handled = true;
        }
    }

    public interface IPointControl
    {
        int ID { get; set; }
        string Name { get; }
        string IP { get; }
        NetworkPointType PointType { get; }
        Point CenterPoint { get; }
        event dPointMove eMoveCenterPoint;
        event HandledEventHandler eRemove;
    }
    public delegate void dPointMove(double X, double Y);
    public enum NetworkPointType
    {
        cloud, hub, server, vpn, line
    }
}
